package com.fub.positioning;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlSerializer;
import android.os.Environment;
import android.util.Log;
import android.util.Xml;

import com.fub.guidance.Point;

public class ReferencePointFilewriter {

	private static String ATTRIBUTE_SS = "ss";
	private static String ATTRIBUTE_SSID = "ssid";
	private static String ATTRIBUTE_LOCATION = "location";
	private static String ATTRIBUTE_BUILDING_ID = "buildingId";
	private static String ATTRIBUTE_X = "x";
	private static String ATTRIBUTE_Y = "y";
	private static String ATTRIBUTE_Z = "z";
	private static String TAG_NAME_RP = "rp";
	private static String TAG_NAME_AP = "ap";
	private static String TAG_NAME_ROOT = "root";

	public List<ReferencePoint> readReferencePoints(String folder,
			String filename) {
		List<ReferencePoint> referencePoints = new ArrayList<ReferencePoint>();
		File rootFolder = new File(Environment.getExternalStorageDirectory(),
				folder);
		if (!rootFolder.exists()) {
			rootFolder.mkdirs();
		}
		File file = new File(rootFolder, filename);
		Element root = getRootElement(file);
		NodeList referencePointNodes = root.getElementsByTagName(TAG_NAME_RP);
		for (int i = 0; i < referencePointNodes.getLength(); i++) {
			Node referencePointNode = referencePointNodes.item(i);
			ReferencePoint referencePoint = parseReferencePointNode(referencePointNode);
			referencePoints.add(referencePoint);
		}
		return referencePoints;
	}

	private ReferencePoint parseReferencePointNode(Node referencePointNode) {
		int x = -1;
		int y = -1;
		int z = -1;
		NamedNodeMap referencePointAttributes = referencePointNode
				.getAttributes();
		ReferencePoint referencePoint = new ReferencePoint();
		for (int i = 0; i < referencePointAttributes.getLength(); i++) {
			Node attribute = referencePointAttributes.item(i);
			if (attribute.getNodeName().equals(ATTRIBUTE_LOCATION)) {
				referencePoint.setLocation(attribute.getNodeValue());
			}
			if (attribute.getNodeName().equals(ATTRIBUTE_X)) {
				x = Integer.parseInt(attribute.getNodeValue());
			}
			if (attribute.getNodeName().equals(ATTRIBUTE_Y)) {
				y = Integer.parseInt(attribute.getNodeValue());
			}
			if (attribute.getNodeName().equals(ATTRIBUTE_Z)) {
				z = Integer.parseInt(attribute.getNodeValue());
				referencePoint.setPosition(new Point(x, y, z));
			}
			if (attribute.getNodeName().equals(ATTRIBUTE_BUILDING_ID)) {
				referencePoint.setBuildingId(attribute.getNodeValue());
			}
		}
		Measurement measurement = new Measurement();
		NodeList accessPoints = referencePointNode.getChildNodes();
		for (int i = 0; i < accessPoints.getLength(); i++) {
			Node accessPoint = accessPoints.item(i);
			NamedNodeMap accessPointAttributes = accessPoint.getAttributes();
			if (accessPointAttributes == null)
				continue;
			String ssid = "noSSID";
			String ss = "-1";
			for (int j = 0; j < accessPointAttributes.getLength(); j++) {
				Node attribute = accessPointAttributes.item(j);
				if (attribute.getNodeName().equals(ATTRIBUTE_SSID)) {
					ssid = attribute.getNodeValue();
				}
				if (attribute.getNodeName().equals(ATTRIBUTE_SS)) {
					ss = attribute.getNodeValue();
					measurement.putSignalStrength(ssid, Integer.parseInt(ss));
				}
			}
		}
		referencePoint.setMeasurement(measurement);
		return referencePoint;
	}

	public void saveReferencePoints(List<ReferencePoint> referencePoints,
			String folder, String fileName) {
		File root = new File(Environment.getExternalStorageDirectory(), folder);
		if (!root.exists()) {
			root.mkdirs();
		}
		File gpxfile = new File(root, fileName);
		FileOutputStream fileos = null;
		try {
			fileos = new FileOutputStream(gpxfile);
		} catch (FileNotFoundException e) {
			Log.e("FileNotFoundException", "can't create FileOutputStream");
		}
		XmlSerializer serializer = Xml.newSerializer();
		try {
			serializer.setOutput(fileos, "UTF-8");
			serializer.startDocument(null, Boolean.valueOf(true));
			serializer.setFeature(
					"http://xmlpull.org/v1/doc/features.html#indent-output",
					true);
			serializer.startTag(null, TAG_NAME_ROOT);
			for (ReferencePoint referencePoint : referencePoints) {
				serializer.startTag(null, TAG_NAME_RP);
				serializer.attribute(null, ATTRIBUTE_LOCATION,
						referencePoint.getLocation());
				serializer.attribute(null, ATTRIBUTE_X, referencePoint
						.getPosition().getX() + "");
				serializer.attribute(null, ATTRIBUTE_Y, referencePoint
						.getPosition().getY() + "");
				serializer.attribute(null, ATTRIBUTE_Z, referencePoint
						.getPosition().getZ() + "");
				serializer.attribute(null, ATTRIBUTE_BUILDING_ID,
						referencePoint.getBuildingId());

				for (String ssid : referencePoint.getMeasurement().getSSids()) {
					serializer.startTag(null, TAG_NAME_AP);
					serializer.attribute(null, ATTRIBUTE_SSID, ssid);
					serializer.attribute(null, ATTRIBUTE_SS, referencePoint
							.getMeasurement().getSingnalStrength(ssid) + "");
					serializer.endTag(null, TAG_NAME_AP);
				}
				serializer.endTag(null, TAG_NAME_RP);
			}
			serializer.endTag(null, TAG_NAME_ROOT);
			serializer.endDocument();
			serializer.flush();
			fileos.close();
		} catch (Exception e) {
			Log.e("Exception", "error occurred while creating xml file");
		}

	}

	private Element getRootElement(File file) {
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document dom = builder.parse(file);
			Element root = dom.getDocumentElement();
			return root;
		} catch (Exception e) {
			throw new IllegalStateException("Document can't be parsed. ");
		}
	}
}
